package com.kk.xhr.admin.biz.impl;

import com.kk.xhr.admin.biz.ICandidateBizService;
import com.kk.xhr.admin.controller.request.CandidateAddRequest;
import com.kk.xhr.admin.controller.request.CandidateModifyRequest;
import com.kk.xhr.admin.controller.request.CandidateQueryRequest;
import com.kk.xhr.admin.controller.vo.CandidateVO;
import com.kk.xhr.common.ErrorCodeEnum;
import com.kk.xhr.common.exception.BusinessException;
import com.kk.xhr.common.pojo.CandidateStatusEnum;
import com.kk.xhr.common.pojo.RecruitStatusEnum;
import com.kk.xhr.model.dto.CandidateDTO;
import com.kk.xhr.model.dto.CandidateQueryRequestDTO;
import com.kk.xhr.model.dto.PageDto;
import com.kk.xhr.model.dto.RecruitDTO;
import com.kk.xhr.model.service.ICandidateService;
import com.kk.xhr.model.service.IRecruitService;
import com.kk.xhr.web.vo.PageVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 候选人biz服务接口实现
 *
 * @author kkmystery
 * @version 1.0 2021/4/6
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
public class CandidateBizServiceImpl implements ICandidateBizService {
    private final ICandidateService candidateService;
    private final IRecruitService recruitService;

    @Override
    public PageVO<CandidateVO> queryPage(CandidateQueryRequest request) {
        PageDto<CandidateDTO> dtos = candidateService.queryPage(CandidateQueryRequestDTO.builder()
            .recruitId(request.getRecruitId())
            .status(request.getStatus())
            .limit(request.getLimit())
            .offset(request.getOffset())
            .build());
        if (0 == dtos.getTotal()) {
            return PageVO.empty();
        }
        return PageVO.fromDTO(dtos, this::generateVO);
    }

    @Override
    public void add(CandidateAddRequest request) {
        candidateService.add(CandidateDTO.builder()
            .recruitId(request.getRecruitId())
            .name(request.getName())
            .email(request.getEmail())
            .phone(request.getPhone())
            .gender(request.getGender())
            .fileId(request.getFileId())
            .remark(request.getRemark())
            .status(CandidateStatusEnum.APPLYING)
            .build());
    }

    @Override
    public void modify(Long id, CandidateModifyRequest request) {
        candidateService.modify(CandidateDTO.builder()
            .id(id)
            .fileId(request.getFileId())
            .remark(request.getRemark())
            .build());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyStatus(Long id, CandidateStatusEnum status) {
        LocalDateTime now = LocalDateTime.now();
        CandidateDTO candidate = candidateService.query(id)
            .orElseThrow(() -> new BusinessException(ErrorCodeEnum.CANDIDATE_NOT_EXIST));
        if (candidate.getStatus() == status) {
            return;
        }
        RecruitDTO recruit = recruitService.query(candidate.getRecruitId())
            .orElseThrow(() -> new BusinessException(ErrorCodeEnum.RECRUIT_NOT_EXIST));
        if (RecruitStatusEnum.PASS == recruit.getStatus()) {
            throw new BusinessException(ErrorCodeEnum.RECRUIT_ALREADY_PASS);
        }
        // 若到达截至时间
        if (recruit.getEndDate().isBefore(now)) {
            recruitService.modifyStatus(recruit.getId(), RecruitStatusEnum.END);
            throw new BusinessException(ErrorCodeEnum.RECRUIT_ALREADY_END);
        }
        // 若为通过则增加通过人数
        if (CandidateStatusEnum.PASS == status) {
            if (recruit.getPassNum() < recruit.getTotal()) {
                if ((recruit.getPassNum() - 1) == recruit.getTotal()) {
                    // 若刚好达标人数, 修改计划状态
                    recruitService.modify(RecruitDTO.builder()
                        .id(recruit.getId())
                        .passNum(recruit.getPassNum() + 1)
                        .status(RecruitStatusEnum.PASS)
                        .build());
                } else {
                    recruitService.modify(RecruitDTO.builder()
                        .id(recruit.getId())
                        .passNum(recruit.getPassNum() + 1)
                        .build());
                }
            }
            if (recruit.getPassNum().equals(recruit.getTotal())) {
                throw new BusinessException(ErrorCodeEnum.RECRUIT_ALREADY_ENOUGH);
            }
        } else {
            // 若之前的状态为pass, 则需要减少通过人数
            if (CandidateStatusEnum.PASS == candidate.getStatus()) {
                recruitService.modify(RecruitDTO.builder()
                    .id(recruit.getId())
                    .passNum(recruit.getPassNum() == 0 ? 0 : recruit.getPassNum() - 1)
                    .build());
            }
        }
        candidateService.modifyStatus(id, status);
    }

    private CandidateVO generateVO(CandidateDTO dto) {
        return CandidateVO.builder()
            .id(dto.getId())
            .email(dto.getEmail())
            .fileId(dto.getFileId())
            .gender(dto.getGender())
            .name(dto.getName())
            .phone(dto.getPhone())
            .remark(dto.getRemark())
            .status(dto.getStatus())
            .build();
    }
}
